package com.example.iqiyitest.view;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.animation.Interpolator;

public class SmoothRecyclerView extends RecyclerView {

	private Method smoothScrollBy;
	private Field mViewFlinger;
	public static final int SCROLL_DURATION = 100;
	private boolean autoScroll = true;

	public SmoothRecyclerView(Context context) {
		super(context);
		init();
	}

	public SmoothRecyclerView(Context context, AttributeSet attrs) {	
		super(context, attrs);
		init();
	}

	public SmoothRecyclerView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}
	
	public void setAutoScroll(boolean autoScroll) {
		this.autoScroll = autoScroll;
	}

	private void init() {
		this.setFocusable(false);
		this.setClipChildren(false);
		try {
			Class<?> mHrecyclerView = RecyclerView.class;
			mViewFlinger = mHrecyclerView.getDeclaredField("mViewFlinger");
			mViewFlinger.setAccessible(true);
			smoothScrollBy = mViewFlinger.getType().getMethod("smoothScrollBy", int.class,
					int.class, int.class, Interpolator.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void smoothScrollBy(int dx, int dy) {
		if(!autoScroll){
			return;
		}
		try {
			int duration = getCusDuration(dx, dy);
			startMovie(duration);
			smoothScrollBy.invoke(mViewFlinger.get(this), dx, dy, duration,
					sQuinticInterpolator);
		} catch (Exception e) {
			e.printStackTrace();
			super.smoothScrollBy(dx, dy);
		}
	}

	public void smoothScrollY(int dy) {
		try {
			int duration = getCusDuration(0, dy);
			startMovie(duration);
			smoothScrollBy.invoke(mViewFlinger.get(this), 0, dy, duration*2, sQuinticInterpolator_y);
		} catch (Exception e) {
			e.printStackTrace();
			super.smoothScrollBy(0, dy);
		}
	}
	
	public void smoothScrollX(int dx) {
		try {
			int duration = getCusDuration(dx, 0);
			startMovie(duration);
			smoothScrollBy.invoke(mViewFlinger.get(this), dx, 0, duration, sQuinticInterpolator);
		} catch (Exception e) {
			e.printStackTrace();
			super.smoothScrollBy(dx, 0);
		}
	}
	
	private int getCusDuration(int dx, int dy) {
		int max = Math.max(Math.abs(dy), Math.abs(dx)) ;
		int duration = max <= SCROLL_DURATION ? max : SCROLL_DURATION;
		return duration;
	}
	
	// 滑动动画校对
	private final Interpolator sQuinticInterpolator_y = new Interpolator() {
		public float getInterpolation(float t) {
			t -= 1;
			return t * t * t* t * t + 1f;
		}
	};

	// 滑动动画校对
	private final Interpolator sQuinticInterpolator = new Interpolator() {
		public float getInterpolation(float t) {
			 return (float) (Math.sin((t - 0.5) * Math.PI) + 1) / 2;
		}
	};
	
	public void startMovie(int duration){
		handler.removeMessages(0);
		moving = true;
		handler.sendEmptyMessageDelayed(0, duration);
	}

	public boolean isMoving() {
		return moving;
	}
	
	@SuppressLint("HandlerLeak")
	private Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			moving = false;
			if(onEndMovie!=null){
				onEndMovie.endMovie();
			}
		};
	};
	
	private boolean moving = false;
	private OnEndMovie onEndMovie;
	public void setOnEndMovie(OnEndMovie onEndMovie) {
		this.onEndMovie = onEndMovie;
	}
	public interface OnEndMovie{
		public void endMovie();
	}
}
